Denne posten beskriver hvordan man kan bruke vekter i R ved hjelp av srvyr- og survey-pakkene. Srvyr-pakka gjør der enkelt å få ut vekta estimater slik som gjennomsnitt og andeler og gjør det enkelt å jobbe med surveyer og spørreundersøkelser. Srvyr bruker ganske standard tidyverse- og dplyr-kode og gjør det mulig å bruke pipe. Dermed blir det mye enklere å få vekta estimater i R.
R har mange styrker, men vekting er ikke en av dem. Vekting er særlig en viktig problematikk når vi bruker surveyer som enten har et skeivt utvalg eller er gjennomført med andre metoder enn tilfeldig trekking, slik som stratifisering (men finn fram Hellevik (2002) for en innføring i ulike trekkemetoder i surveyer). I R er det ikke lagt opp til vekting fra start og det er ikke slik at man lett kan få vekta resultater. For regresjon er det som regel mulig å spesifisere vekter med weights=
eller tilsvarende, men ellers krever det som regel pakker som ikke er del av base R, dvs. pakkene som følger med R når man laster det ned.
For andre typer estimater slik som gjennomsnitt eller andeler er det ikke like rett fram å bruke vekter uten å laste inn pakker. Det er imidlertid gjort et veldig godt arbeid med survey-pakka. Denne pakka gir mange muligheter til å spesifisere ulike vekter og beregne ulike estimater. Dessverre har forfatteren av pakka funnet på en syntaks som ikke likner på noen annen pakke jeg i hvert fall har brukt. Dette gjør at det er en ganske stor kneik å lære seg surveypakka og at man ikke kan bruke vanlig syntaks fra tidyverse eller data.table noe som kan frustrere mange (har jeg skjønt. Snakker ikke av erfaring. Neida. Joda!). Heldigvis fiksa noen biffen ved å lage srvyr-pakka som gjør det mulig å bruke mer standard tidyverse-syntaks samtidig som man får fordelene av survey-pakka.
Srvyr er en pakka som gjør det mulig å bruke vekteverktøy fra survey-pakka (se rant over) med tidyverse-syntaks. Srvyr forenkler dermed estimering av vekta estimater i R. Srvyr kan enkelt gi oss vekta snitt, andeler, antall observasjoner osv. Her kommer en enkel innføring, men se også Srvyr sin egen side for mer informasjon.
I dette eksempelet bruker jeg den siste runden av European Social Survey (runde 9) for Norge. Datafila er tilgjengelig på nettsida til European Social Survey
Det første man må gjøre i Srvyr
er å lage et surveyobjekt. Det sentrale man gjør da er å spesifisere hvilken variabel som gir vekten i datasettet. I ESS er det hensiktsmessig å bruk anweight
,når man bare jobber med ett land, men sjekk ut vekteguiden til ESS. Survey-objektet er litt vanskelig å jobbe med så det kan være lurt å beholde en data.frame eller liknende en å kunne sjekke hvilke variabler du har eller se på enkeltvariabler
ess9_no_surv <- ess9_no %>%
as_survey_design(weights = anweight)
Når vi har spesifisert vekten og lagd et survey-objekt kan vi bruke Srvyr til å regne ut vektede estimater. I Srvyr bruker vi Pipe %\>%
og kan bruke mye standard tidyversekode slik som mutate, filter og group_by. Srvyr introduserer noen egne funksjoner for å beregne vekta estimater. Dette er for eksempel survey_mean og survey_prop. Som vanlig med tidyverse kan vi begynne med å spesifisere hvilke utvalg vi er interessert i med filter()
og onkode variabler med mutate()
før vi beregner estimatene med summarise()
.
For å beregne vekta gjennomsnitt kan vi bruke funksjonen survey_mean()
. Hvis vi lurer på hvor tillitsfulle nordmenn er i snitt kan vi bruke variabelen ppltrst
som er et ellevepunktsspørsmål hvor ytterpunktene på skalaen er «folk flest er til å stole på» og «du kan ikke være for forsiktig». Dette er et spørsmål som er mye brukt til å måle tillit og der særlig Skandinavia har skilt seg ut med høye nivåer.
For å beregne vekta gjennomsnitt bruker vi survey_mean()
inne i en sunmarise()
. Her vil jeg bare ha det første estimatet siden dette er snittet og jeg ikke er interessert i standardavviket. Jeg bruker i tillegg na.rm=TRUE
fordi jeg vil at funksjonen skal se bort fra missingverdier. Jeg regner i tillegg ut det uvekta snittet med mean()
slik at se vekta og uvekta estimatene kan sammenliknes.
tillit <- ess9_no_surv %>%
summarise(variabel="ppltrst",
vekta_snitt=survey_mean(ppltrst,na.rm=T)[1],
#denne gir standardavviket også som standard, men det trengte jeg ikke her
uvekta_snitt=mean(ppltrst,na.rm=T))
# skriver ut tabellen
tillit %>%
kable(digits = 2)
variabel | vekta_snitt | uvekta_snitt |
---|---|---|
ppltrst | 6.59 | 6.76 |
Vi ser at snittet blir høyere når vi ikke vekter enn når vi vekter. Dette gir mening. Vektene gjør at personer som svarer sjeldnere på undersøkelser får større betydning. At denne gruppa har lavere tillit enn andre er ikke overraskende. Lav tillit kan være en av årsakene til at denne gruppa ikke svarer i like stor grad som andre.
Ofte er vi ikke bare interessert i gjennomsnittsnivået på en variabel, men også hvor stor andel av respondentene som har svart de ulike alternativene. I Srvyr brukes group_by til å spesifisere variabelen vi vil regne ut andelene for. Vi grupperer på variabelen vi vil ha andelene for og så bruker vi summarise og survey_mean uten å spesifisere noen variabel inne i survey_mean. Da gir survey_mean() bare andelene som har svart hvert nivå på variabelen. Under regner jeg ut andelen som har oppgitt at de har stemt på hvert av partiene både vekta og uvekta.
#partivar:
#ess9_no$prtclbno
#regner ut vekta andeler per parti
partiandel_vekt<- ess9_no_surv %>%
#tar vekk missing
filter(prtclbno<12) %>%
#grupperer ettrr parti
group_by(`Parti`=as_factor(prtclbno)) %>%
# survey_mean gir andel når den brukes uten noen variabel inni
# vi ganger med hundre for å få prosent
summarise(Prosent=survey_prop()[1]*100)
# regner ut uvekta andeler
partiandel_uten<-ess9_no_surv %>%
#tar vekk missing
filter(prtclbno<12) %>%
#grupperer ettrr parti
group_by(`Parti`=as_factor(prtclbno)) %>%
summarise(n=n()) %>%
summarise(Parti,Prosent=n/sum(n)*100)
# slår sammen i en tabell og
partiandel_begge <- full_join(partiandel_vekt,partiandel_uten,by="Parti",suffix = c(" vekta"," uvekta"))
#printer tabellen med ett desimal
partiandel_begge %>%
kable(digits = 1)
Parti | Prosent vekta | Prosent uvekta |
---|---|---|
Rødt | 3.7 | 3.7 |
Sosialistisk Venstreparti | 9.4 | 10.1 |
Arbeiderpartiet | 32.6 | 30.7 |
Venstre | 3.4 | 4.0 |
Kristelig Folkeparti | 4.1 | 4.3 |
Senterpartiet | 9.2 | 8.9 |
Høyre | 23.7 | 25.0 |
Fremskrittspartiet | 8.8 | 8.0 |
Miljøpartiet De Grønne | 4.3 | 4.3 |
Other | 0.8 | 1.1 |
Vi ser igjen et forståelig mønster. Frp, Ap og Sp har velgere som vektes opp. Høyre, SV, Venstre og Krf vektes ned. Altså tyder tabellen på at velgerne av de første partiene er vanskeligere å nå enn velgerne av de siste partiene.
Vi kan enkelt lage en figur av resultatene med ggplot2. ggplot2 vil gjerne ha tidye data, det vil si at hver verdi får sin rad. Tabellen over er ikke tidy fordi hver rad har to verdier, vekta og uvekta. For å få dataene tidy bruker vi pivot_longer
. Det er kolonne 2 og 3 som har tallverdiene og vi vil at at verdikolonnen skal hete «Prosent». Kolonnenavnene til kolonne 2 og 3 vil vi lagre i kolonna «Vekting». Inne i ggplot() bruker vi aes() til å spsifisere hvilke variabler som skal være x og y-aksene og at vektingkolonna bestemmer fyllfargen til søylene. Så sier vi at vi vil ha søyler med geom_col() og at søylene skal stå ved siden av hverandre og ikke oppå hverandre. Jeg flipper figuren så det blir plass til partinavnene, bruker et svart-hvitt tema og plasserer forklaringen under figuren. Til slutt spesifiserer jeg tittelen.
partiandel_begge %>%
pivot_longer(cols = 2:3,values_to = "Prosent",names_to = "Vekting") %>%
ggplot(aes(x=Parti,y = Prosent,fill=Vekting)) +
geom_col(position = position_dodge())+
coord_flip()+
theme_bw()+
theme(legend.position="bottom")+
labs(title = "Vekta og uvekta partioppslutning i ESS9")
For attribution, please cite this work as
Solheim (2022, Dec. 16). Solheim: Data med vekter i R. Retrieved from https://www.oyvindsolheim.com/code/Vekter i R/
BibTeX citation
@misc{solheim2022data, author = {Solheim, Øyvind Bugge}, title = {Solheim: Data med vekter i R}, url = {https://www.oyvindsolheim.com/code/Vekter i R/}, year = {2022} }